using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
using Resources;
using ScrewTurn.Wiki.PluginFramework;

namespace ScrewTurn.Wiki
{
    public partial class Edit : BasePage
    {
        private bool disableAjaxPreview;
        private bool previewClassic;

        protected void Page_Load(object sender, EventArgs e)
        {
            Page.Title = Messages.EditTitle + " - " + Settings.WikiTitle;
            lblPreview.CssClass = "";
            lblPreview.Text = "";

            txtPageName.Attributes.Add("onkeydown",
                                       @"javascript:var keycode; if(window.event) keycode = event.keyCode; else keycode = event.which; if(keycode == 9) { __GetServerElementById('txtTitle').focus(); return false; }");
            txtTitle.Attributes.Add("onkeydown",
                                    @"javascript:var keycode; if(window.event) keycode = event.keyCode; else keycode = event.which; if(keycode == 9) { __GetServerElementById('txtContent').focus(); return false; }");

            txtContent.Attributes.Add("onkeyup", "javascript:storeCaret(this); return false");
            txtContent.Attributes.Add("onclick", "javascript:storeCaret(this); return false");

            string ua = Request.UserAgent;
            if (!string.IsNullOrEmpty(ua))
            {
                ua = ua.ToLowerInvariant();
                StringBuilder sbua = new StringBuilder();
                sbua.Append(@"<script type=""text/javascript"">");
                sbua.Append("\r\n<!--\r\n");
                if (ua.Contains("gecko"))
                {
                    // Mozilla
                    sbua.Append("addEventListener('beforeunload', __UnloadPage, true);");
                }
                else
                {
                    // IE
                    sbua.Append("window.attachEvent('onbeforeunload', __UnloadPage);");
                }
                sbua.Append("\r\n// -->\r\n");
                sbua.Append("</script>");
                lblUnloadPage.Text = sbua.ToString();

                if (ua.Contains("konqueror") || ua.Contains("safari")) disableAjaxPreview = true;
            }

            PrintRefreshLink();
            PrintStrings();
            PrintEditNotice();
            PrintLabels();
            PrintAjaxEnabler();
            PrintPrePreview();
            PrintPostPreview();
            PrintSessionRefresh();
            PrintCustomSpecialTags();

            if (Request.Cookies[Settings.LoginCookieName] != null && SessionFacade.LoginKey == null)
            {
                Response.Redirect("Login.aspx?Redirect=" +
                                  Tools.UrlEncode(
                                      Request.Url.ToString().Substring(
                                          Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
            }

            if (Page.IsPostBack) return;

            // Load PageList
            StringBuilder sb = new StringBuilder();
            List<PageInfo> pages = Pages.Instance.AllPages;
            sb.AppendFormat("<script type=\"text/javascript\">\r\n<!--\r\n__AllPages = new Array({0});\r\n", pages.Count);
            for (int i = 0; i < pages.Count; i++)
            {
                sb.AppendFormat("__AllPages[{0}] = '{1}'; ", i, pages[i].Name.Replace("'", "&apos;"));
            }
            sb.Append("// -->\r\n</script>\r\n");
            lblPageList.Text = sb.ToString();

            // Load snippets
            StringBuilder sb2 = new StringBuilder();
            List<Snippet> snippets = Snippets.Instance.AllSnippets;
            for (int i = 0; i < snippets.Count; i++)
            {
                sb2.Append(@"<a href=""#"" class=""snippetlistlink"" onclick=""javascript:return __Insert('{S:");
                sb2.Append(snippets[i].Name.Replace("'", "&apos;"));
                int parms = CountParameters(snippets[i]);
                for (int k = 0; k < parms; k++)
                {
                    sb2.AppendFormat("|P{0}", k + 1);
                }
                sb2.Append(@"}');"">");
                sb2.Append(snippets[i].Name);
                if (parms > 0)
                {
                    sb2.AppendFormat(" ({0} parms)", parms);
                }
                sb2.Append("</a>");
            }
            lblSnippetList.Text = sb2.ToString();

            if (Request["File"] != null)
            {
                if (SessionFacade.LoginKey == null || !SessionFacade.Admin)
                {
                    Response.Redirect("AccessDenied.aspx");
                }

                // Check filename to avoid editing of unallowed files
                string filename = Request["File"].ToLower(CultureInfo.CurrentCulture);
                string[] editableFiles = Settings.EditableFiles;
                bool found = false;
                for (int i = 0; i < editableFiles.Length; i++)
                {
                    if (filename.Equals(editableFiles[i].ToLower(CultureInfo.CurrentCulture)))
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    Response.Redirect("AccessDenied.aspx");
                }

                txtPageName.Visible = false;
                txtTitle.Visible = false;
                lblTitle.Visible = false;
                lblCategories.Visible = false;
                lstCategories.Visible = false;
                lblNewCategoryResult.Visible = false;
                txtNewCategory.Visible = false;
                btnNewCategory.Visible = false;
                lblEditComment.Visible = false;
                txtComment.Visible = false;
                lblGlobalTitle.Text = Messages.EditingFile + ": " + Request["File"];
                if (!File.Exists(Settings.PublicDirectory + Request["File"]))
                {
                    lblPreview.CssClass = "resulterror";
                    lblPreview.Text = Messages.FileNotFound;
                    return;
                }
                txtContent.Text = Tools.LoadFile(Settings.PublicDirectory + Request["File"]);
                if (Request["Action"] != null && Request["Action"].ToLowerInvariant().Equals("edit"))
                {
                }
                else
                {
                    txtContent.ReadOnly = true;
                    btnSave.Enabled = false;
                }
                return;
            }

            PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);

            if (Request["Page"] != null && Pages.IsValidName(Request["Page"]))
            {
                txtUploadDirectory.Text = Request["Page"];
            }

            if (pageInfo == null)
            {
                if (SessionFacade.LoginKey == null)
                {
                    if (!Settings.PublicAccess)
                    {
                        Response.Redirect("Login.aspx?Redirect=Edit.aspx");
                    }
                }
                else
                {
                    if (!Settings.UsersCanCreateNewPages && !SessionFacade.Admin)
                    {
                        Response.Redirect("AccessDenied.aspx");
                    }
                }
                lblGlobalTitle.Text = Messages.CreatePage + ": ";
                txtPageName.Visible = true;
            }

            // Display only legal Categories (i.e. Categories managed by the provider of the page, or the default provider is the page is not available)
            List<CategoryInfo> cats = new List<CategoryInfo>(Pages.Instance.GetAvailableCategories(pageInfo));
            cats.Sort(new CategoryNameComparer());
            lstCategories.Items.Clear();
            for (int i = 0; i < cats.Count; i++)
            {
                lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
            }

            if ((!Settings.UsersCanManagePageCategories && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
                (!Settings.UsersCanManagePageCategories && SessionFacade.LoginKey == null))
            {
                // Disable Category management
                lstCategories.Enabled = false;
            }
            if ((!Settings.UsersCanCreateNewCategories && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
                (!Settings.UsersCanCreateNewCategories && SessionFacade.LoginKey == null))
            {
                // Disable Category creation
                txtNewCategory.Visible = false;
                btnNewCategory.Visible = false;
                lblNewCategoryResult.Visible = false;
            }
            if ((!Settings.UsersCanUploadFiles && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
                (!Settings.UsersCanUploadFiles && SessionFacade.LoginKey == null))
            {
                // Disable Quick Upload
                updFile.Enabled = false;
            }

            if (pageInfo != null)
            {
                if (pageInfo.Provider.ReadOnly) Response.Redirect(pageInfo.Name + Settings.PageExtension);
                Content.GetFormattedPageContent(pageInfo, true);


                if (pageInfo.Status == PageStatus.Locked)
                {
                    if (SessionFacade.LoginKey == null ||
                        (SessionFacade.LoginKey != null && (SessionFacade.LoginKey == null || !SessionFacade.Admin)))
                    {
                        Response.Redirect("AccessDenied.aspx");
                    }
                }

                // Login/Authorization check
                if (SessionFacade.LoginKey == null && !Settings.PublicAccess && pageInfo.Status != PageStatus.Public)
                {
                    Response.Redirect("Login.aspx?Redirect=" +
                                      Tools.UrlEncode(
                                          Request.Url.ToString().Substring(
                                              Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
                }
                if ((Settings.PublicAccess || pageInfo.Status == PageStatus.Public) && SessionFacade.LoginKey == null)
                {
                    lblIpLogged.Visible = true;
                }

                CheckEditingCollisions();

                lblGlobalTitle.Text = Messages.EditPage + ": " + pageInfo.Name;
                PageContent c = Content.GetPageContent(pageInfo, false);

                txtTitle.Text = c.Title;

                if (Request["Section"] != null)
                {
                    // Load only a single section of the page
                    int section = -1;
                    try
                    {
                        section = int.Parse(Request["Section"]);
                    }
                    catch
                    {
                    }
                    if (section == -1) txtContent.Text = c.Content;
                    else
                    {
                        List<HPosition> hPos = Formatter.DetectHeaders(c.Content);
                        int start, len;
                        string dummy = "";
                        ExtractSection(c.Content, section, out start, out len, out dummy);
                        txtContent.Text = c.Content.Substring(start, len);
                        // Extract the title of the selected Section
                        string sectionTitle = txtContent.Text.Split('\n')[0];
                        sectionTitle = sectionTitle.Substring(0, sectionTitle.LastIndexOf("=="));
                            // Search for at at least two '='
                        sectionTitle = sectionTitle.Trim('=');
                        // Append it to the Global Title
                        lblGlobalTitle.Text += " / " + sectionTitle /* + " [" + section.ToString() + "]"*/;
                    }
                    // This is needed to avoid content corruption
                    btnSaveAndContinue.Visible = false;
                }
                else
                {
                    txtContent.Text = c.Content;
                }

                // Select currently used Categories
                CategoryInfo[] categories = Pages.Instance.GetCategoriesPerPage(pageInfo);
                for (int i = 0; i < categories.Length; i++)
                {
                    for (int k = 0; k < lstCategories.Items.Count; k++)
                    {
                        if (categories[i].Name.Equals(lstCategories.Items[k].Value))
                        {
                            lstCategories.Items[k].Selected = true;
                            break;
                        }
                    }
                }
            }
            else
            {
                if (SessionFacade.LoginKey == null && !Settings.PublicAccess)
                {
                    Response.Redirect("Login.aspx?Redirect=Edit.aspx?Page=" + Request["Page"]);
                }
                if (!Settings.UsersCanCreateNewPages && !SessionFacade.Admin)
                {
                    Response.Redirect("AccessDenied.aspx");
                }
                lblGlobalTitle.Text = Messages.CreatePage + ": ";
                txtPageName.Visible = true;
                txtPageName.Text = Request["Page"];

                if (SessionFacade.Admin)
                {
                    pnlProvider.Visible = true;

                    IPagesStorageProvider[] pgs = Collectors.PagesProviderCollector.AllProviders;
                    for (int i = 0; i < pgs.Length; i++)
                    {
                        if (!pgs[i].ReadOnly)
                        {
                            ListItem li = new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString());
                            if (pgs[i].GetType().ToString().Equals(Settings.DefaultPagesProvider)) li.Selected = true;
                            lstProvider.Items.Add(li);
                        }
                    }
                }
            }

            captcha.Visible = SessionFacade.LoginKey == null && !Settings.DisableCaptchaControl;
        }

        private int CountParameters(Snippet s)
        {
            Regex regex = new Regex("\\?[0-9]+\\?");
            List<string> parms = new List<string>();
            foreach (Match m in regex.Matches(s.Content))
            {
                if (m.Success && !parms.Contains(m.Value)) parms.Add(m.Value);
            }
            return parms.Count;
        }

        private void ExtractSection(string content, int section, out int start, out int len, out string anchor)
        {
            List<HPosition> hPos = Formatter.DetectHeaders(content);
            start = 0;
            len = content.Length;
            anchor = "";
            int level = -1;
            bool found = false;
            for (int i = 0; i < hPos.Count; i++)
            {
                if (hPos[i].ID == section)
                {
                    start = hPos[i].Index;
                    len = len - start;
                    level = hPos[i].Level; // Level is used to edit the current section AND all the subsections
                    // Set the anchor value so that it's possible to redirect the user to the just edited section
                    anchor = Formatter.BuildHAnchor(hPos[i].Text);
                    found = true;
                    break;
                }
            }
            if (found)
            {
                int diff = len;
                for (int i = 0; i < hPos.Count; i++)
                {
                    if (hPos[i].Index > start && // Next section (Hx)
                        hPos[i].Index - start < diff && // The nearest section
                        hPos[i].Level <= level)
                    {
                        // Of the same level or higher
                        len = hPos[i].Index - start - 1;
                        diff = hPos[i].Index - start;
                    }
                }
            }
        }

        private void PrintCustomSpecialTags()
        {
            Dictionary<string, CustomToolbarItem> tags = Host.Instance.CustomSpecialTags;
            StringBuilder sb = new StringBuilder(100);
            foreach (string key in tags.Keys)
            {
                switch (tags[key].Item)
                {
                    case ToolbarItem.SpecialTag:
                        sb.AppendFormat(
                            "<a href=\"#\" onclick=\"javascript:return __Insert('{0}');\" class=\"specialtaglink\">{1}</a>",
                            tags[key].Value, key);
                        break;
                    case ToolbarItem.SpecialTagWrap:
                        string[] t = tags[key].Value.Split('|');
                        sb.AppendFormat(
                            "<a href=\"#\" onclick=\"javascript:return __Wrap('{0}', '{1}');\" class=\"specialtaglink\">{2}</a>",
                            t[0], t[1], key);
                        break;
                }
            }
            lblCustomSpecialTags.Text = sb.ToString();
        }

        private void PrintLabels()
        {
            if (Page.IsPostBack) return;

            lblFileManagement.Text = Messages.FileManagement;

            lblBuildAnchor.Text = Messages.Anchor;
            lblBuildAnchorLink.Text = Messages.AnchorLink;

            lblImageLeft.Text = Messages.ImageLeft;
            lblImageRight.Text = Messages.ImageRight;
            lblImageAuto.Text = Messages.ImageAuto;
            lblImageInline.Text = Messages.ImageInline;

            lblTextareaSize.Text = Messages.TextareaSize;
            lblBigger.Text = Messages.Bigger;
            lblSmaller.Text = Messages.Smaller;
            lblAuto.Text = Messages.Auto;
        }

        private void CheckEditingCollisions()
        {
            PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);
            if (pageInfo == null) return;

            string username = Request.UserHostAddress;
            if (SessionFacade.LoginKey != null) username = SessionFacade.Username;

            if (Collisions.Instance.IsEdited(pageInfo, username))
            {
                pnlConcurrentEditing.Visible = true;
                lblConcurrentEditingUsername.Text = "(" +
                                                    Users.Instance.UserLink(Collisions.Instance.WhosEditing(pageInfo)) +
                                                    ")";
                if (Settings.DisableConcurrentEditing)
                {
                    lblSaveDisabled.Visible = true;
                    lblSaveDangerous.Visible = false;
                    btnSave.Enabled = false;
                    btnSaveAndContinue.Enabled = false;
                }
                else
                {
                    lblSaveDisabled.Visible = false;
                    lblSaveDangerous.Visible = true;
                    btnSave.Enabled = true;
                    btnSaveAndContinue.Enabled = true;
                }
            }
            else
            {
                pnlConcurrentEditing.Visible = false;
                btnSave.Enabled = true;
                btnSaveAndContinue.Enabled = true;
            }
        }

        public void PrintEditNotice()
        {
            string n;
            if (!Content.PseudoCache.TryGetValue("EditNotice", out n))
            {
                n = Formatter.Format(Tools.LoadFile(Settings.EditNoticeFile), null);
                Content.PseudoCache["EditNotice"] = n;
            }
            lblEditNotice.Text = "<br /><br />" + n;
        }

        protected void btnSaveAndContinue_Click(object sender, EventArgs e)
        {
            btnSave_Click(sender, e);
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (!Page.IsValid) return;

            // Re-verify authentication
            PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);
            if (pageInfo == null)
            {
                // Page creation
                if (SessionFacade.LoginKey == null && !Settings.PublicAccess)
                {
                    Response.Redirect("Login.aspx?Redirect=Edit.aspx?Page=" + Request["Page"]);
                }
                if (!Settings.UsersCanCreateNewPages && !SessionFacade.Admin)
                {
                    Response.Redirect("AccessDenied.aspx");
                }
            }
            else
            {
                // Page modification
                if (pageInfo.Provider.ReadOnly) Response.Redirect(pageInfo.Name + Settings.PageExtension);

                if (pageInfo.Status == PageStatus.Locked)
                {
                    if (SessionFacade.LoginKey == null ||
                        (SessionFacade.LoginKey != null && (SessionFacade.LoginKey == null || !SessionFacade.Admin)))
                    {
                        Response.Redirect("AccessDenied.aspx");
                    }
                }

                // Login/Authorization check
                if (SessionFacade.LoginKey == null && !Settings.PublicAccess && pageInfo.Status != PageStatus.Public)
                {
                    Response.Redirect("Login.aspx?Redirect=" +
                                      Tools.UrlEncode(
                                          Request.Url.ToString().Substring(
                                              Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
                }
                if ((Settings.PublicAccess || pageInfo.Status == PageStatus.Public) && SessionFacade.LoginKey == null)
                {
                    lblIpLogged.Visible = true;
                }
            }

            // Check for scripts
            if (!Settings.ScriptTagsAllowed)
            {
                Regex r = new Regex(@"\<script.*?\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                if (r.Match(txtContent.Text).Success)
                {
                    lblResult.Text = @"<span style=""color: #FF0000;"">" + Messages.ScriptDetected + "</span>";
                    return;
                }
            }

            bool redirect = true;
            if (sender == btnSaveAndContinue) redirect = false;

            if (Request["File"] != null)
            {
                Log.LogEntry("File update requested for " + Request["File"], EntryType.General, SessionFacade.Username);
                Tools.WriteFile(Settings.PublicDirectory + Request["File"], txtContent.Text);
                Content.PseudoCache.Clear();
                if (redirect) Response.Redirect("Admin.aspx");
                lblResult.Text = Messages.FileSaved;
                return;
            }

            txtPageName.Style.Clear();
            txtTitle.Style.Clear();

            lblResult.Text = "";
            lblResult.CssClass = "";

            if (txtPageName.Visible && txtPageName.Enabled)
            {
                if (!Pages.IsValidName(txtPageName.Text))
                {
                    lblResult.CssClass = "resulterror";
                    lblResult.Text = Messages.InvalidPageName;
                    txtPageName.Style.Add("background-color", "#FF6600");
                    return;
                }
                else
                {
                    PageInfo info = Pages.Instance.FindPage(txtPageName.Text);
                    if (info != null)
                    {
                        lblResult.CssClass = "resulterror";
                        lblResult.Text = Messages.PageAlreadyExists;
                        txtPageName.Style.Add("background-color", "#FF6600");
                        return;
                    }
                }
            }
            if (txtTitle.Text.Replace(" ", "").Length == 0)
            {
                lblResult.CssClass = "resulterror";
                lblResult.Text = Messages.InvalidPageTitle;
                txtTitle.Style.Add("background-color", "#FF6600");
                return;
            }

            string username = "";
            if (SessionFacade.LoginKey == null) username = Request.UserHostAddress;
            else username = SessionFacade.Username;

            // Create list of selected categories
            List<CategoryInfo> categories = new List<CategoryInfo>();
            for (int i = 0; i < lstCategories.Items.Count; i++)
            {
                if (lstCategories.Items[i].Selected)
                    categories.Add(Pages.Instance.FindCategory(lstCategories.Items[i].Value));
            }

            txtComment.Text = txtComment.Text.Trim();

            if (txtPageName.Visible)
            {
                PageInfo pg = Pages.Instance.FindPage(txtPageName.Text);
                bool bak = true;
                if (pg == null)
                {
                    if (pnlProvider.Visible)
                        Pages.Instance.CreatePage(txtPageName.Text,
                                                  Collectors.PagesProviderCollector.GetProvider(
                                                      lstProvider.SelectedValue));
                    else Pages.Instance.CreatePage(txtPageName.Text);
                    pg = Pages.Instance.FindPage(txtPageName.Text);
                    bak = false;
                    txtUploadDirectory.Text = pg.Name;
                }
                Log.LogEntry("Page update requested for " + txtPageName.Text, EntryType.General, username);
                Pages.Instance.ModifyPage(pg, txtTitle.Text, username, DateTime.Now, txtComment.Text, txtContent.Text,
                                          bak);
                Pages.Instance.Rebind(pg, categories.ToArray());
                lblResult.Text = "<span style=\"color: #009900;\">" + Messages.PageSaved + "</span>";

                if (redirect)
                {
                    Collisions.Instance.Cancel(pg, username);
                    Response.Redirect(Tools.UrlEncode(txtPageName.Text) + Settings.PageExtension + "?NoRedirect=1");
                }
                else
                {
                    // Disable PageName, because the name cannot be changed anymore
                    txtPageName.Enabled = false;
                }
            }
            else
            {
                // Used for redirecting to a specific section after editing it
                string anchor = "";

                PageInfo info = Pages.Instance.FindPage(Request["Page"]);
                if (Request["Section"] == null &&
                    txtContent.Text.Replace("\r", "").Equals(Content.GetPageContent(info, false).Content))
                {
                    // Save only MetaData
                    Log.LogEntry("Page Meta update requested for " + info.Name, EntryType.General, username);
                    Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text,
                                              txtContent.Text, false);
                }
                else
                {
                    // Save all the data
                    Log.LogEntry("Page update requested for " + info.Name, EntryType.General, username);
                    int section = -1;
                    try
                    {
                        section = int.Parse(Request["Section"]);
                    }
                    catch
                    {
                    }
                    if (section == -1)
                    {
                        Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text,
                                                  txtContent.Text, true);
                    }
                    else
                    {
                        StringBuilder sb = new StringBuilder();
                        PageContent cont = Content.GetPageContent(info, false);
                        int start, len;
                        ExtractSection(cont.Content, section, out start, out len, out anchor);
                        if (start > 0) sb.Append(cont.Content.Substring(0, start));
                        sb.Append(txtContent.Text);
                        if (start + len < cont.Content.Length - 1) sb.Append(cont.Content.Substring(start + len));
                        Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text,
                                                  sb.ToString(), true);
                    }
                }
                // Save Categories binding
                Pages.Instance.Rebind(info, categories.ToArray());

                lblResult.Text = "<span style=\"color: #009900;\">" + Messages.PageSaved + "</span>";
                if (redirect)
                {
                    Collisions.Instance.Cancel(info, username);
                    Response.Redirect(Tools.UrlEncode(info.Name) + Settings.PageExtension + "?NoRedirect=1" +
                                      (!string.IsNullOrEmpty(anchor) ? ("#" + anchor) : ""));
                }
            }
        }

        protected void btnPreview_Click(object sender, EventArgs e)
        {
            // Check for scripts
            if (!Settings.ScriptTagsAllowed)
            {
                Regex r = new Regex(@"\<script.*?\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                if (r.Match(txtContent.Text).Success)
                {
                    lblResult.CssClass = "resulterror";
                    lblResult.Text = Messages.ScriptDetected;
                    return;
                }
            }

            previewClassic = true;

            lblPrePreview.Text = "";

            lblPreview.Text = "";
            lblPreview.Text = @"<div id=""PreviewDivExternal"">";
            lblPreview.Text += @"<p><a href=""javascript:__HidePreview();"">" + Messages.HidePreview + @"</a><br />";
            lblPreview.Text += @"<span style=""color: #FF0000;"">" + Messages.ThisIsAPreview + "</span></p><br />";
            lblPreview.Text += @"<div id=""PreviewDiv"">";

            lblPreview.Text += Formatter.Format(txtContent.Text, null);

            lblPreview.Text += "</div>";
            lblPreview.Text += @"</div><div class=""clear"" />";

            lblPostPreview.Text = "";

            lblResult.Text = @"<span style=""color: #009900;"">" + Messages.PreviewCreated + "</span>";
        }

        public void PrintAjaxEnabler()
        {
            if (!disableAjaxPreview)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(@"<script type=""text/javascript"">" + "\n<!--\n");
                sb.Append("__GetServerElementById('btnPreview').onclick = __LoadPreview;" + "\n");
                sb.Append("// -->\n</script>" + "\n");
                lblAjaxEnabler.Text = sb.ToString();
            }
            else lblAjaxEnabler.Text = "";
        }

        public void PrintPrePreview()
        {
            if (!disableAjaxPreview && !previewClassic)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(@"<div id=""PreviewDivExternal"" style=""display: none;"">");
                sb.Append(@"<p><a href=""#"" onclick=""__HidePreview();"">");
                sb.Append(Messages.HidePreview);
                sb.Append("</a><br />");
                sb.Append(@"<span style=""color: #FF0000;"">");
                sb.Append(Messages.ThisIsAPreview);
                sb.Append("</span></p><br />");
                sb.Append(@"<div id=""PreviewDiv"">");
                lblPrePreview.Text = sb.ToString();
            }
            else lblPrePreview.Text = "";
        }

        public void PrintPostPreview()
        {
            if (!disableAjaxPreview && !previewClassic)
            {
                lblPostPreview.Text = @"</div></div><div class=""clear"" />";
            }
            else lblPostPreview.Text = "";
        }

        protected void btnCancel_Click(object sender, EventArgs e)
        {
            if (txtPageName.Visible)
            {
                Response.Redirect(Settings.DefaultPage + Settings.PageExtension);
            }
            else
            {
                PageInfo p = Pages.Instance.FindPage(Request["Page"]);
                string username = Request.UserHostAddress;
                if (SessionFacade.LoginKey != null) username = SessionFacade.Username;

                if (p != null)
                {
                    Collisions.Instance.Cancel(p, username);
                    Response.Redirect(Request["Page"] + Settings.PageExtension);
                }
                else if (Request["File"] != null) Response.Redirect("Admin.aspx");
            }
        }

        public void PrintStrings()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(@"<script type=""text/javascript"">" + "\n<!--\n");
            sb.Append(@"var __StringLinkTitle = """ + Messages.LinkTitle + @""";" + "\n");
            sb.Append(@"var __StringLinkUrl = """ + Messages.LinkUrl + @""";" + "\n");
            sb.Append(@"var __StringAnchorId = """ + Messages.AnchorId + @""";" + "\n");
            sb.Append(@"var __StringAnchorTitle = """ + Messages.AnchorTitle + @""";" + "\n");
            sb.Append(@"var __StringImageTitle = """ + Messages.ImageTitle + @""";" + "\n");
            sb.Append(@"var __StringImageUrl = """ + Messages.ImageUrl + @""";" + "\n");
            sb.Append(@"var __StringImageBigUrl = """ + Messages.ImageBigUrl + @""";" + "\n");
            sb.Append(@"var __PreviewCreated = """ + Messages.PreviewCreated + @""";" + "\n");
            sb.Append(@"var __EnterTitleAndUrl = """ + Messages.EnterTitleAndUrl + @""";" + "\n");
            sb.Append(@"var __ScriptDetected = """ + Messages.ScriptDetected + @""";" + "\n");
            sb.Append(@"var __ScriptAllowed = " + Settings.ScriptTagsAllowed.ToString().ToLowerInvariant() + @";" + "\n");
            sb.Append("// -->\n</script>" + "\n");
            lblStrings.Text = sb.ToString();
        }

        protected void btnNewCategory_Click(object sender, EventArgs e)
        {
            lblNewCategoryResult.Text = "";
            lblNewCategoryResult.CssClass = "";

            if (!Pages.IsValidName(txtNewCategory.Text))
            {
                lblNewCategoryResult.CssClass = "resulterror";
                lblNewCategoryResult.Text = Messages.InvalidCategoryName;
                return;
            }
            if (Pages.Instance.FindCategory(txtNewCategory.Text) == null)
            {
                PageInfo p = null;
                p = Pages.Instance.FindPage(Request["Page"]);

                if (pnlProvider.Visible)
                {
                    Pages.Instance.CreateCategory(txtNewCategory.Text,
                                                  Collectors.PagesProviderCollector.GetProvider(
                                                      lstProvider.SelectedValue));
                }
                else
                {
                    Pages.Instance.CreateCategory(txtNewCategory.Text, (p != null ? p.Provider : null));
                }

                // Save selected categories
                List<string> selected = new List<string>();
                for (int i = 0; i < lstCategories.Items.Count; i++)
                {
                    if (lstCategories.Items[i].Selected) selected.Add(lstCategories.Items[i].Value);
                }

                // Reload list
                lstCategories.Items.Clear();
                CategoryInfo[] cats = null;
                if (pnlProvider.Visible)
                {
                    cats = Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue).AllCategories;
                }
                else
                {
                    cats = Pages.Instance.GetAvailableCategories(p);
                }
                for (int i = 0; i < cats.Length; i++)
                {
                    lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
                }

                // Re-select correct categories and the new one
                for (int i = 0; i < lstCategories.Items.Count; i++)
                {
                    bool found = false;
                    for (int k = 0; k < selected.Count; k++)
                    {
                        if (lstCategories.Items[i].Value.Equals(selected[k]))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (found || lstCategories.Items[i].Value.Equals(txtNewCategory.Text))
                        lstCategories.Items[i].Selected = true;
                }
            }
            txtNewCategory.Text = "";
        }

        protected void lstProvider_SelectedIndexChanged(object sender, EventArgs e)
        {
            CategoryInfo[] cats = Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue).AllCategories;
            lstCategories.Items.Clear();
            for (int i = 0; i < cats.Length; i++)
            {
                lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
            }
        }

        public void PrintRefreshLink()
        {
            PageInfo page = Pages.Instance.FindPage(Request["Page"]);
            if (page != null)
            {
                lblRefreshLink.Text = @"<a href=""Edit.aspx?Page=" + Tools.UrlEncode(page.Name) +
                                      (Request["Section"] != null ? "&amp;Section=" + Request["Section"] : "") + @""">" +
                                      Messages.Refresh + " &raquo;</a>";
            }
        }

        public void PrintSessionRefresh()
        {
            PageInfo p = Pages.Instance.FindPage(Request["Page"]);
            StringBuilder sb = new StringBuilder();
            sb.Append(@"<iframe src=""");
            if (p != null) sb.Append("SessionRefresh.aspx?Page=" + Tools.UrlEncode(p.Name));
            else sb.Append("SessionRefresh.aspx");
            sb.Append(@""" style=""width: 1px; height: 1px; border: none;"" scrolling=""no""></iframe>");

            lblSessionRefresh.Text = sb.ToString();
        }

        protected void btnUpload_Click(object sender, EventArgs e)
        {
            lblUploadResult.Text = "";

            if ((!Settings.UsersCanUploadFiles && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
                (!Settings.UsersCanUploadFiles && SessionFacade.LoginKey == null))
            {
                // Upload not allowed
                Response.Redirect("AccessDenied.aspx");
            }

            string partialName = txtUploadDirectory.Text + "\\" + updFile.FileName;
            string fullName = Settings.UploadDirectory + partialName;
            fullName = fullName.Replace("\\\\", "\\");

            if (!updFile.HasFile)
            {
                lblUploadResult.CssClass = "resulterror";
                lblUploadResult.Text = Messages.FileVoid;
                return;
            }
            if (File.Exists(fullName))
            {
                lblUploadResult.CssClass = "resulterror";
                lblUploadResult.Text = Messages.FileAlreadyExists;
                return;
            }
            string[] allowedFileTypes = Settings.AllowedFileTypes;
            bool found = false;
            for (int i = 0; i < allowedFileTypes.Length; i++)
            {
                if (
                    Path.GetExtension(updFile.FileName).ToLower(CultureInfo.CurrentCulture).Equals("." +
                                                                                                   allowedFileTypes[i].
                                                                                                       ToLowerInvariant()))
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                Log.LogEntry(
                    "Unallowed file type upload attempt blocked (" + Path.GetExtension(updFile.FileName) + ")",
                    EntryType.Warning, SessionFacade.Username);
                lblUploadResult.CssClass = "resulterror";
                lblUploadResult.Text = Messages.UnallowedFileType;
                return;
            }
            if (updFile.FileBytes.Length > Settings.MaxFileSize*1024)
            {
                Log.LogEntry("File too big (" + updFile.FileBytes.Length + ")", EntryType.Warning,
                             SessionFacade.Username);
                lblUploadResult.CssClass = "resulterror";
                lblUploadResult.Text = Messages.FileTooBig;
                return;
            }
            // Delete cached thumbnails (if any)
            Tools.DeleteThumbnails(partialName);
            if (!Directory.Exists(Path.GetDirectoryName(fullName)))
                Directory.CreateDirectory(Path.GetDirectoryName(fullName));
            updFile.SaveAs(fullName);
            lblUploadResult.CssClass = "resultok";
            lblUploadResult.Text = Messages.FileSaved;
            Log.LogEntry("File " + updFile.FileName + " uploaded", EntryType.General, SessionFacade.Username);

            jsftTree.RenderContent();
            jsimBrowser.RenderContent();
        }
    }
}